/**
 * Copyright (c) 2016-2019, Michael Yang 杨福海 (fuhai999@gmail.com).
 * <p>
 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl-3.0.txt
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.jpress.module.article.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Page;
import io.jboot.Jboot;
import io.jboot.utils.StrUtils;
import io.jboot.web.controller.annotation.RequestMapping;
import io.jboot.web.controller.validate.EmptyValidate;
import io.jboot.web.controller.validate.Form;
import io.jpress.JPressConsts;
import io.jpress.commons.layer.SortKit;
import io.jpress.core.menu.annotation.AdminMenu;
import io.jpress.core.template.TemplateManager;
import io.jpress.model.Menu;
import io.jpress.model.User;
import io.jpress.module.article.model.*;
import io.jpress.module.article.service.*;
import io.jpress.service.MenuService;
import io.jpress.service.UserService;
import io.jpress.web.base.AdminControllerBase;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import javax.inject.Inject;
import java.util.List;
import java.util.Set;

/**
 * @author Michael Yang 杨福海 （fuhai999@gmail.com）
 * @version V1.0
 * @Package io.jpress.module.article.admin
 */
@RequestMapping("/admin/article")
public class _ArticleController extends AdminControllerBase {

    @Inject
    private ArticleService articleService;
    @Inject
    private ArticleCategoryService categoryService;
    @Inject
    private ArticleCommentService commentService;
    @Inject
    private BannerService bannerService;
    @Inject
    private ArticleGoodsService articleGoodsService;
    @Inject
    private UserService userService;


    @AdminMenu(text = "文章管理", groupId = "article", order = 0)
    public void index() {

        String status = getPara("status");
        String title = getPara("title");
        Long categoryId = getParaToLong("categoryId");

        Page<Article> page =
                StringUtils.isBlank(status)
                        ? articleService._paginateWithoutTrash(getPagePara(), 10, title, categoryId)
                        : articleService._paginateByStatus(getPagePara(), 10, title, categoryId, status);

        setAttr("page", page);

        int draftCount = articleService.findCountByStatus(Article.STATUS_DRAFT);
        int trashCount = articleService.findCountByStatus(Article.STATUS_TRASH);
        int normalCount = articleService.findCountByStatus(Article.STATUS_NORMAL);
        setAttr("draftCount", draftCount);
        setAttr("trashCount", trashCount);
        setAttr("normalCount", normalCount);
        setAttr("totalCount", draftCount + trashCount + normalCount);


        List<ArticleCategory> categories = categoryService.findListByType(ArticleCategory.TYPE_CATEGORY);
        SortKit.toLayer(categories);
        setAttr("categories", categories);

        flagCheck(categories, categoryId);

        render("article/article_list.html");
    }

    public void articlePreview(){
        Long articleId = getParaToLong("articleId");

        Article article = articleService.findById(articleId);

        JSONArray contentItems = JSON.parseArray(article.getContent());

        setAttr("title",article.getTitle());
        setAttr("contentItems",contentItems);
        render("article/article_preview.html");
    }




    private void initStylesAttr(String prefix) {
        List<String> styles = TemplateManager.me().getCurrentTemplate().getSupportStyles(prefix);
        if (styles != null && !styles.isEmpty()) {
            setAttr("styles", styles);
        }
    }

    private void flagCheck(List<ArticleCategory> categories, Long... checkIds) {
        if (checkIds == null || checkIds.length == 0
                || categories == null || categories.size() == 0) {
            return;
        }

        for (ArticleCategory category : categories) {
            for (Long id : checkIds) {
                if (id != null && id.equals(category.getId())) {
                    category.put("isCheck", true);
                }
            }
        }
    }


    @EmptyValidate({
            @Form(name = "article.title", message = "标题不能为空"),
            @Form(name = "article.content", message = "文章内容不能为空")
    })
    public void doWriteSave() {
        Article article = getModel(Article.class, "article");

        if (!validateSlug(article)) {
            renderJson(Ret.fail("message", "slug不能全是数字且不能包含字符：- "));
            return;
        }


        if (StrUtils.isNotBlank(article.getSlug())) {
            Article slugArticle = articleService.findFirstBySlug(article.getSlug());
            if (slugArticle != null && slugArticle.getId().equals(article.getId()) == false) {
                renderJson(Ret.fail("message", "该slug已经存在"));
                return;
            }
        }


        long id = articleService.doGetIdBySaveOrUpdateAction(article);
        articleService.doUpdateCommentCount(id);

        Long[] categoryIds = getParaValuesToLong("category");
        Long[] tagIds = getTagIds(getParaValues("tag"));

        Long[] allIds = ArrayUtils.addAll(categoryIds, tagIds);

        articleService.doUpdateCategorys(id, allIds);

        if (allIds != null && allIds.length > 0) {
            for (Long categoryId : allIds) {
                categoryService.updateCount(categoryId);
            }
        }

        Ret ret = id > 0 ? Ret.ok().set("id", id) : Ret.fail();
        renderJson(ret);
    }

    private Long[] getTagIds(String[] tags) {
        if (tags == null || tags.length == 0) {
            return null;
        }

        List<ArticleCategory> categories = categoryService.doNewOrFindByTagString(tags);
        long[] ids = categories.stream().mapToLong(value -> value.getId()).toArray();
        return ArrayUtils.toObject(ids);
    }


    @AdminMenu(text = "文章分类", groupId = "article", order = 2)
    public void category() {
        List<ArticleCategory> categories = categoryService.findListByType(ArticleCategory.TYPE_CATEGORY);
        SortKit.toLayer(categories);
        setAttr("categories", categories);
        int id = getParaToInt(0, 0);
        if (id > 0) {
            for (ArticleCategory category : categories) {
                if (category.getId() == id) {
                    setAttr("category", category);
                }
            }
        }
        initStylesAttr("artlist_");
        render("article/category_list.html");
    }


    @AdminMenu(text = "商品管理", groupId = "article", order = 4)
    public void goodsManage() {
        String keyword = getPara("keyword");
        Long articleId = getParaToLong("articleId");
        Page<ArticleGoods> page;
        if(articleId != null){
            Article article = articleService.findById(articleId);
            setAttr("articleId",articleId);
            setAttr("articleTitle",article.getTitle());
            page = articleGoodsService._paginateByArticleId(getPagePara(),10,articleId,keyword);
        }else {
            page = articleGoodsService._paginate(getPagePara(),10,keyword);
        }

        setAttr("page",page);
        render("article/goods_list.html");
    }

    public void doAddCategoryToMenu() {

        Long id = getIdPara();

        ArticleCategory category = categoryService.findById(id);
        if (category == null) {
            renderJson(Ret.fail().set("message", "该数据已经被删除"));
            return;
        }

        Menu menu = new Menu();
        menu.setPid(0l);
        menu.setUrl(category.getUrl());
        menu.setText(category.getTitle());
        menu.setType(io.jpress.model.Menu.TYPE_MAIN);
        menu.setRelativeTable("article_category");
        menu.setRelativeId(id);
        menu.setOrderNumber(9);

        MenuService menuService = Jboot.bean(MenuService.class);
        menuService.saveOrUpdate(menu);

        renderJson(Ret.ok());
    }


    @EmptyValidate({
            @Form(name = "category.title", message = "分类名称不能为空")
    })
    public void doCategorySave() {
        ArticleCategory category = getModel(ArticleCategory.class, "category");
        if (!validateSlug(category)) {
            renderJson(Ret.fail("message", "slug不能全是数字且不能包含字符：- "));
            return;
        }

        categoryService.saveOrUpdate(category);
        categoryService.updateCount(category.getId());
        renderJson(Ret.ok());
    }

    @EmptyValidate({
            @Form(name = "category.title", message = "标签名称不能为空"),
    })
    public void doTagSave() {
        ArticleCategory category = getModel(ArticleCategory.class, "category");
        //标签管理页面添加的标签没有slug，无法显示对应标签下的文章列表 wanghui 2018.11.7
        category.setSlug(category.getTitle());
        if (!validateSlug(category)) {
            renderJson(Ret.fail("message", "slug不能全是数字且不能包含字符：- "));
            return;
        }

        categoryService.saveOrUpdate(category);
        categoryService.updateCount(category.getId());
        renderJson(Ret.ok());
    }

    public void doCategoryDel() {
        categoryService.deleteById(getIdPara());
        renderJson(Ret.ok());
    }


    @AdminMenu(text = "文章评论", groupId = "article", order = 5)
    public void comment() {

        String status = getPara("status");
        String key = getPara("keyword");
        Long articleId = getParaToLong("articleId");

        Page<ArticleComment> page =
                StrUtils.isBlank(status)
                        ? commentService._paginateWithoutTrash(getPagePara(), 10, articleId, key)
                        : commentService._paginateByStatus(getPagePara(), 10, articleId, key, status);

        setAttr("page", page);

        long unauditedCount;
        long trashCount;
        long normalCount;
        if(articleId != null){
            unauditedCount = commentService.findCountByArticleIdAndStatus(articleId,ArticleComment.STATUS_UNAUDITED);
            trashCount = commentService.findCountByArticleIdAndStatus(articleId,ArticleComment.STATUS_TRASH);
            normalCount = commentService.findCountByArticleIdAndStatus(articleId,ArticleComment.STATUS_NORMAL);
            setAttr("articleId",articleId);
            setAttr("articleTitle",articleService.findById(articleId).getTitle());
        }else {
            unauditedCount = commentService.findCountByStatus(ArticleComment.STATUS_UNAUDITED);
            trashCount = commentService.findCountByStatus(ArticleComment.STATUS_TRASH);
            normalCount = commentService.findCountByStatus(ArticleComment.STATUS_NORMAL);
        }
        setAttr("unauditedCount", unauditedCount);
        setAttr("trashCount", trashCount);
        setAttr("normalCount", normalCount);
        setAttr("totalCount", unauditedCount + trashCount + normalCount);

        render("article/comment_list.html");
    }


    /**
     * 评论回复 页面
     */
    public void commentReply() {
        long id = getIdPara();
        ArticleComment comment = commentService.findById(id);
        ArticleComment pidComment = commentService.findByPid(id);
        setAttr("pidComment",pidComment);
        setAttr("comment", comment);
        render("article/comment_reply.html");
    }

    public void commentArticle(){
        Long articleId = getParaToLong("articleId");

        if(articleId != null){
            Article article = articleService.findById(articleId);
            List<User> users = userService.findByCreateSource(User.SOURCE_VIRTUAL_USER);
            setAttr("users",users);
            setAttr("articleId",articleId);
            setAttr("articleTitle",article.getTitle());
        }
        render("article/comment_article.html");
    }

    /**
     * 评论编辑 页面
     */
    public void commentEdit() {
        long id = getIdPara();
        ArticleComment comment = commentService.findById(id);
        setAttr("comment", comment);
        render("article/comment_edit.html");
    }

    public void doCommentSave() {
        ArticleComment comment = getBean(ArticleComment.class, "comment");
        commentService.saveOrUpdate(comment);
        renderJson(Ret.ok());
    }


    /**
     * 进行评论回复
     */
    public void doCommentReply() {
        User user = getLoginedUser();

        String content = getPara("content");
        Long articleId = getParaToLong("articleId");
        Long pid = getParaToLong("pid");

        ArticleComment comment = commentService.findByPid(pid);
        if(comment == null){
            comment = new ArticleComment();
            comment.setAuthor(user.getNickname());
            comment.setContent(content);
            comment.setUserId(user.getId());
            comment.setStatus(ArticleComment.STATUS_NORMAL);
            comment.setArticleId(articleId);
            comment.setPid(pid);
            commentService.save(comment);
        }else {
            comment.setContent(content);
            commentService.update(comment);
        }
        renderJson(Ret.ok());
    }
    @EmptyValidate({
            @Form(name = "content", message = "评论内容不能为空")
            ,@Form(name = "articleId", message = "文章不能为空")
            ,@Form(name = "userId", message = "用户不能为空")
    })
    public void doArticleComment() {
        String content = getPara("content");
        Long articleId = getParaToLong("articleId");
        Long userId = getParaToLong("userId");
        User user = userService.findById(userId);
        ArticleComment comment = new ArticleComment();
        comment.setContent(content);
        comment.setUserId(user.getId());
        comment.setStatus(ArticleComment.STATUS_NORMAL);
        comment.setArticleId(articleId);
        comment.setAuthor(user.getNickname());

        commentService.save(comment);
        articleService.doIncArticleCommentCount(articleId);
        renderJson(Ret.ok());
    }

    /**
     * 删除评论
     */
    public void doCommentDel() {
        Long id = getParaToLong("id");
        commentService.deleteById(id);
        renderJson(Ret.ok());
    }

    public void doGoodsDel(){
        Long id = getParaToLong("id");
        articleGoodsService.deleteById(id);
        renderJson(Ret.ok());
    }

    /**
     * 批量删除评论
     */
    public void doCommentDelByIds() {
        String ids = getPara("ids");
        if (StrUtils.isBlank(ids)) {
            renderJson(Ret.fail());
            return;
        }

        Set<String> idsSet = StrUtils.splitToSet(ids, ",");
        if (idsSet == null || idsSet.isEmpty()) {
            renderJson(Ret.fail());
            return;
        }
        render(commentService.deleteByIds(idsSet.toArray()) ? Ret.ok() : Ret.fail());
    }

    /**
     * 批量删除商品
     */
    public void doGoodsDelByIds() {
        String ids = getPara("ids");
        if (StrUtils.isBlank(ids)) {
            renderJson(Ret.fail());
            return;
        }

        Set<String> idsSet = StrUtils.splitToSet(ids, ",");
        if (idsSet == null || idsSet.isEmpty()) {
            renderJson(Ret.fail());
            return;
        }
        render(articleGoodsService.deleteByIds(idsSet.toArray()) ? Ret.ok() : Ret.fail());
    }


    /**
     * 批量审核评论
     */
    public void doCommentAuditByIds() {
        String ids = getPara("ids");
        if (StrUtils.isBlank(ids)) {
            renderJson(Ret.fail());
            return;
        }

        Set<String> idsSet = StrUtils.splitToSet(ids, ",");
        if (idsSet == null || idsSet.isEmpty()) {
            renderJson(Ret.fail());
            return;
        }
        render(commentService.batchChangeStatusByIds(ArticleComment.STATUS_NORMAL, idsSet.toArray()) ? Ret.ok() : Ret.fail());
    }


    /**
     * 修改评论状态
     */
    public void doCommentStatusChange(Long id, String status) {
        render(commentService.doChangeStatus(id, status) ? Ret.ok() : Ret.fail());
    }

    @AdminMenu(text = "设置", groupId = "article", order = 7)
    public void setting() {
        render("article/setting.html");
    }


    public void doDel() {
        Long id = getIdPara();
        render(articleService.deleteById(id) ? Ret.ok() : Ret.fail());
    }

    public void doDelByIds() {
        String ids = getPara("ids");
        if (StrUtils.isBlank(ids)) {
            renderJson(Ret.fail());
            return;
        }

        Set<String> idsSet = StrUtils.splitToSet(ids, ",");
        if (idsSet == null || idsSet.isEmpty()) {
            renderJson(Ret.fail());
            return;
        }
        render(articleService.deleteByIds(idsSet.toArray()) ? Ret.ok() : Ret.fail());
    }


    public void doTrash() {
        Long id = getIdPara();
        render(articleService.doChangeStatus(id, Article.STATUS_TRASH) ? Ret.ok() : Ret.fail());
    }

    public void doDraft() {
        Long id = getIdPara();
        render(articleService.doChangeStatus(id, Article.STATUS_DRAFT) ? Ret.ok() : Ret.fail());
    }

    public void doNormal() {
        Long id = getIdPara();
        render(articleService.doChangeStatus(id, Article.STATUS_NORMAL) ? Ret.ok() : Ret.fail());
    }

    public void doUpdateOrderNum(){
        Long id = getParaToLong("id");
        Long orderNum = getParaToLong("orderNum");
        if(id == null ){
            Ret.fail();
        }
        if(orderNum == null){
            orderNum = 0L;
        }
        Article article = articleService.findById(id);
        article.setOrderNumber(orderNum);
        render(article.update() ? Ret.ok():Ret.fail());
    }

    public void doUpdateViewCount(){
        Long id = getParaToLong("id");
        Long viewCount = getParaToLong("viewCount");
        if(id == null){
            Ret.fail();
        }
        if(viewCount == null){
            viewCount = 0L;
        }
        Article article = articleService.findById(id);
        article.setViewCount(viewCount);
        render(article.update() ? Ret.ok():Ret.fail());
    }

    public void doUpdateCommentOrderNum(){
        Long id = getParaToLong("id");
        Long orderNum = getParaToLong("orderNum");
        if(id == null || orderNum == null){
            Ret.fail();
        }
        ArticleComment articleComment = commentService.findById(id);
        articleComment.setOrderNumber(orderNum);
        render(articleComment.update() ? Ret.ok():Ret.fail());
    }



    @AdminMenu(text = "小程序banner", groupId = "article", order = 6)
    public void banner(){
//        List<Banner> banners = bannerService.findListByType(Banner.TYPE_WECHAT_MINIPROGRAM);
        List<Banner> banners = bannerService.findAll();
        setAttr("banners", banners);
        int id = getParaToInt(0, 0);
        if (id > 0) {
            for (Banner banner : banners) {
                if (banner.getId() == id) {
                    setAttr("banner", banner);
                }
            }
        }
        initStylesAttr("artlist_");
        render("article/banner_list.html");
    }

    @EmptyValidate({
            @Form(name = "banner.img_url", message = "图片不能为空")
    })
    public void doBannerSave() {
        Banner banner = getModel(Banner.class, "banner");
        bannerService.saveOrUpdate(banner);
        renderJson(Ret.ok());
    }

    public void doBannerDel() {
        bannerService.deleteById(getIdPara());
        renderJson(Ret.ok());
    }


    @AdminMenu(text = "写文章", groupId = "article", order = 1)
    public void write() {

        List<ArticleCategory> categories = categoryService.findListByType(ArticleCategory.TYPE_CATEGORY);
        SortKit.toLayer(categories);
        setAttr("categories", categories);


        int articleId = getParaToInt(0, 0);

        Article article = null;
        if (articleId > 0) {
            article = articleService.findById(articleId);
            if (article == null) {
                renderError(404);
                return;
            }
            setAttr("article", article);

            List<ArticleCategory> tags = categoryService.findListByArticleId(articleId, ArticleCategory.TYPE_TAG);
            setAttr("tags", tags);

            Long[] categoryIds = categoryService.findCategoryIdsByArticleId(articleId);
            flagCheck(categories, categoryIds);
        }

        String editMode = article == null ? getCookie(JPressConsts.COOKIE_EDIT_MODE) : article.getEditMode();
        setAttr("editMode", JPressConsts.EDIT_MODE_MARKDOWN.equals(editMode)
                ? JPressConsts.EDIT_MODE_MARKDOWN
                : JPressConsts.EDIT_MODE_HTML);

        initStylesAttr("article_");

        render("article/article_write.html");
    }


}
